#include "errorcodestableview.h"
#include <QHeaderView>
#include <QAbstractItemModel>
#include <QDebug>
#include <QResizeEvent>
#include <list>

#include "types.h"
#include "sconst.h"
#include "databaseinstancemngr.h"
#include "qmysqldabasemngr.h"
#include "dbq_getterror4module.h"
#include "qpopup.h"

const static char module_id_separator_start[] = "[";
const static char module_id_separator_end[] = "]";

const QString ErrorCodesTableView::COLUMN_NAME[ErrorCodesTableView::COLUMN_MAX] = {
  "Module Name",
  "Error ID",
  "Short Description",
  "Full Description"
};

const int ErrorCodesTableView::COLUMN_WIDTH_PREFERED[ErrorCodesTableView::COLUMN_MAX] = {
    150,   /* COLUMN_ID_MODULE_NAME                               */
    90,    /* COLUMN_ID_ERROR_CODE_ID                             */
    400,   /* COLUMN_ID_ERROR_CODE_SHORT_DESCRIPTION              */
    600    /* COLUMN_ID_ERROR_CODE_FULL_DESCRIPTION [rest value]  */
};

const int ErrorCodesTableView::minimumTableWidth = ErrorCodesTableView::COLUMN_WIDTH_PREFERED[ErrorCodesTableView::COLUMN_ID_MODULE_NAME] +
                                                   ErrorCodesTableView::COLUMN_WIDTH_PREFERED[ErrorCodesTableView::COLUMN_ID_ERROR_CODE_ID] +
                                                   ErrorCodesTableView::COLUMN_WIDTH_PREFERED[ErrorCodesTableView::COLUMN_ID_ERROR_CODE_SHORT_DESCRIPTION] +
                                                   ErrorCodesTableView::COLUMN_WIDTH_PREFERED[ErrorCodesTableView::COLUMN_ID_ERROR_CODE_FULL_DESCRIPTION];

mysqlquery::dbq_getallerrors ErrorCodesTableView::db_query_get_all_errors            = mysqlquery::dbq_getallerrors();
mysqlquery::dbq_geterror4module ErrorCodesTableView::db_query_get_errors_4_module    = mysqlquery::dbq_geterror4module();
mysqlquery::dbq_geterrorbyid ErrorCodesTableView::db_query_get_error_by_id           = mysqlquery::dbq_geterrorbyid();


ErrorCodesTableView::ErrorCodesTableView(QString table_name, QWidget *parent,  QSqlDatabase db) : QTableWidget(parent)
{
  UNUSED_ARGUMENT(table_name);
  UNUSED_ARGUMENT(db);

  setItemPrototype(getNewCellWidgetInstance());
  setSelectionMode(SingleSelection);
  setSelectionBehavior(QAbstractItemView::SelectRows);
  setEditTriggers(QTableWidget::NoEditTriggers);

  connect(horizontalHeader(),SIGNAL(sectionResized(int,int,int)), this,
          SLOT(updateSectionWidth(int,int,int)));
  connect(verticalHeader(),SIGNAL(sectionResized(int,int,int)), this,
          SLOT(updateSectionHeight(int,int,int)));

  connect(verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(verticalHeaderSectionClicked(int)));

  connect(this, SIGNAL(cellClicked(int,int)), this, SLOT(cellClicked(int,int)));

  setHorizontalScrollMode(ScrollPerPixel);
  setVerticalScrollMode(ScrollPerPixel);

  clear();
}

CellWidget* ErrorCodesTableView::getNewCellWidgetInstance()
{
  return new CellWidget;
}


void ErrorCodesTableView::clear()
{
  setRowCount(0);
  setColumnCount(0);
  setColumnCount(COLUMN_MAX);

  for(int icolumn_count = 0; icolumn_count < COLUMN_MAX; icolumn_count++)
  {
    QTableWidgetItem *pitem = getNewCellWidgetInstance();
    pitem->setText(COLUMN_NAME[icolumn_count]);
    setColumnWidth(icolumn_count, COLUMN_WIDTH_PREFERED[icolumn_count]);
    setHorizontalHeaderItem(icolumn_count, pitem);
  }

  QHeaderView *pHeaderView = horizontalHeader();
  pHeaderView->setStretchLastSection(true);
  setCurrentCell(0,0);
}


void ErrorCodesTableView::verticalHeaderSectionClicked(int index)
{
  QHeaderView *pVerticalHeader = verticalHeader();
  QSize qs = pVerticalHeader->size();
  int x = this->columnViewportPosition(0);
  int y = this->rowViewportPosition(index);

  QPoint pos = QPoint(x,y);
  pos = mapToGlobal(pos);
  x = pos.x() + qs.width();
  pos.setX(x);

  QPopup *pPopup = QPopup::getInstance();
  pPopup->text(getErrorCodeDescription(getErrorID(index)));
#if 0
  pPopup->text("Hello this is popup widget with out timer\n"
                  "start next string\n");
#endif
  pPopup->move(pos);
  pPopup->showPopup();
}


void ErrorCodesTableView::cellClicked ( int row, int column )
{
  long errorid = getErrorID(row);
  const Errorcode ec = (const Errorcode)getErrorCode(errorid);

//  qDebug() << "ErrorCodesTableView::cellClicked(...)";

  UNUSED_ARGUMENT(column);

  emit setErrorCode(ec);
}

Module ErrorCodesTableView::getModule(int rowID)
{
  Module  module;
  int     module_id;
  QString module_name;
  QString str = getCellString(rowID, ErrorCodesTableView::COLUMN_ID_MODULE_NAME);
  QStringList list = str.split(module_id_separator_start);

  module_name = list.at(0);
  str = list.at(1);
  list = str.split(module_id_separator_end);
  module_id = list.at(0).toInt();

  module.setModuleName(module_name.toStdString());
  module.setModuleID(module_id);
  return module;
}

long ErrorCodesTableView::getErrorID(int rowID)
{
  QString str = getCellString(rowID, ErrorCodesTableView::COLUMN_ID_ERROR_CODE_ID);
  return str.toLong();
}

Errorcode ErrorCodesTableView::getErrorCode(const long &errorid, bool offline)
{
  mysqlquery::dbquerygeterror  *pquery = 0;
  errorcodelistresult          *perrocoderesult = 0;
  DataBaseInstanceMngr         *pdbinstmngr    = DataBaseInstanceMngr::getDataBaseInstanceMngr();
  QMySqlDatabaseManager        *pmysqldbmngr  = (QMySqlDatabaseManager*)pdbinstmngr->getDatabaseManager(SC_ERROR_CODE_DB_NAME);

  UNUSED_ARGUMENT(offline);

  db_query_get_error_by_id.setErrorID(errorid);
  pquery = &db_query_get_error_by_id;

  ListQVariant lv = pmysqldbmngr->query(pquery->getSqlQuery());

  perrocoderesult = ((errorcodelistresult*)pquery);
  std::list<Errorcode> l = perrocoderesult->getErrorList(lv);
  Errorcode ec = (Errorcode)(*l.begin());
  return ec;
}

QString ErrorCodesTableView::getErrorCodeDescription(const long &errorid)
{
  QString   result;
  Errorcode ec = getErrorCode(errorid);

/** format error code to string *****************************************************************************/
  result  = "ERROR ID: " + QString::number(ec.getErrorID()) + "\n";
  result += "Module: " + ec.getModule().data() + ":" + QString::number(ec.getModule().getInstance()) + "\n";
  result += "Short description: " + QString(ec.getShortDescription().c_str()) + "\n";
  result += "Full description: " + QString(ec.getLongDescription().c_str()) + "\n";
  return result;
}

void ErrorCodesTableView::updateSectionWidth(int logicalIndex, int, int newSize)
{
  if(newSize < ErrorCodesTableView::COLUMN_WIDTH_PREFERED[logicalIndex])
    setColumnWidth(logicalIndex, ErrorCodesTableView::COLUMN_WIDTH_PREFERED[logicalIndex]);
}

void ErrorCodesTableView::updateSectionHeight(int logicalIndex, int, int newSize)
{
  setRowHeight(logicalIndex, newSize);
}


void ErrorCodesTableView::updateTable(const Module &m)
{
  DataBaseInstanceMngr         *pdbinstmngr    = DataBaseInstanceMngr::getDataBaseInstanceMngr();
  QMySqlDatabaseManager        *pmysqldbmngr  = (QMySqlDatabaseManager*)pdbinstmngr->getDatabaseManager(SC_ERROR_CODE_DB_NAME);
  mysqlquery::dbquerygeterror  *pquery = 0;
  errorcodelistresult          *perrocoderesult = 0;

  if(m.getModuleID() == ALL_MODULE_ID)
    pquery = &db_query_get_all_errors;
  else {
    db_query_get_errors_4_module.setModule(m);
    pquery = &db_query_get_errors_4_module;
  }

  ListQVariant lv = pmysqldbmngr->query(pquery->getSqlQuery());

  perrocoderesult = ((errorcodelistresult*)pquery);
  std::list<Errorcode> l = perrocoderesult->getErrorList(lv);
  std::list<Errorcode>::iterator ec_it;

  clear();
  for (ec_it = l.begin() ; ec_it != l.end(); ec_it++ )
  {
    Errorcode ec = (Errorcode)(*ec_it);
    addErrorcode(ec);
  }
}


CellWidget *ErrorCodesTableView::getCell(int row, int column) const
{
  return static_cast<CellWidget *>(item(row, column));
}

void ErrorCodesTableView::setCellString(int row, int column, const QString &data)
{
  CellWidget *pitem = getCell(row, column);
  if (!pitem) {
    pitem = getNewCellWidgetInstance();
    pitem->setTextAlignment(Qt::AlignLeft);
  }
  pitem->setText(data);
  setItem(row, column, pitem);
}

QString ErrorCodesTableView::getCellString(int row, int column) const
{
  CellWidget *c = getCell(row, column);
  if (c) {
    return c->text();
  } else {
    return "";
  }
}

QString ErrorCodesTableView::text(int row, int column) const
{
  return getCellString(row, column);
}

void ErrorCodesTableView::addErrorcode(Errorcode ec, int row)
{
  int     latestRow = rowCount() - 1;
  int     rowcount = rowCount();
  QString display_module;

  if(row <= 0 || latestRow < row) {
   insertRow(rowcount);
   row  = rowcount;
  }

  display_module = QString(ec.getModule().getModuleName().c_str()) + " " +
                   module_id_separator_start +
                   QString::number(ec.getModule().getModuleID()) +
                   module_id_separator_end;

  setCellString(row, COLUMN_ID_MODULE_NAME, display_module);
  setCellString(row, COLUMN_ID_ERROR_CODE_ID, QString::number(ec.getErrorID()));
  setCellString(row, COLUMN_ID_ERROR_CODE_SHORT_DESCRIPTION, ec.getShortDescription().c_str());
  setCellString(row, COLUMN_ID_ERROR_CODE_FULL_DESCRIPTION, ec.getLongDescription().c_str());
}
